using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
using UnityEngine.ResourceManagement.ResourceLocations;

public class TestAddressable : MonoBehaviour
{
    // Start is called before the first frame update
    string logStr = "";
    string packageName = "MainPackage";
    string packageName2 = "SubPackage";
    string localVersion = "1.0"; 

    void Start()
    {
        Application.logMessageReceived += log;
        Addressables.InitializeAsync();
        // StartCoroutine(IEInit());
    }

    void log(string logString, string stackTrace, LogType type)
    {
        logStr += logString + "\n";
    }

    void CreatePackage(string pkgName)
    {
        
    }
    
    // private string cdnUrl = $"https://a.unity.cn/client_api/v1/buckets/518accc9-9650-4828-98c2-bf7369494f41/content/YooAsset";
    private string cdnUrl1 = $"http://127.0.0.1:8900/Addressable";
    private string cdnUrl2 = $"http://127.0.0.1:8900/Addressable_2";
    private string curUrl =  $"http://127.0.0.1:8900/Addressable";
    private List<string> catalogs = new List<string>();
    async Task CheckUpdate()
    {
        catalogs.Clear();
        var check = Addressables.CheckForCatalogUpdates(false);
        await check.Task;
        if (check.Status == UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationStatus.Succeeded)
        {
            catalogs.AddRange(check.Result);
            if (catalogs != null && catalogs.Count > 0)
            {
                Debug.Log("有更新");
            }
            else
            {
                Debug.Log("没有更新");
            }
        }
        Addressables.Release(check);
    }

    List<object> updateList = new List<object>();

    async Task UpdateCatalogs(List<string> catalogs)
    {
        updateList.Clear();
        if (catalogs.Count > 0)
        {
            var updateCatalogs = Addressables.UpdateCatalogs(catalogs, false);
            await updateCatalogs.Task;
            Debug.Log("更新数量：" + updateCatalogs.Result.Count);
            if (updateCatalogs.Result != null && updateCatalogs.Result.Count > 0)
            {
                foreach (var locator in updateCatalogs.Result)
                {
                    foreach (var key in locator.Keys)
                    {
                        updateList.Add(key);
                        Debug.Log("更新内容：" + key);
                    }
                }
            }
            Addressables.Release(updateCatalogs);
        }
    }

    async Task Download(List<object> updateList)
    {
        if (updateList.Count > 0)
        {
            var sizeHander = Addressables.GetDownloadSizeAsync((IEnumerable<object>)updateList);
            await sizeHander.Task;
            Debug.Log("更新大小：" + sizeHander.Result);
            Addressables.Release(sizeHander);
            downLoadHandle = Addressables.DownloadDependenciesAsync((IEnumerable<object>)updateList,
                Addressables.MergeMode.Union,
                false);
            await downLoadHandle.Task;
            Debug.Log("下载完成");
            Addressables.Release(downLoadHandle);
        }
    }

    private AsyncOperationHandle downLoadHandle;
    private void Update()
    {
        if (!downLoadHandle.IsValid() && !downLoadHandle.IsDone)
        {
            Debug.Log("下载中" +downLoadHandle.GetDownloadStatus().Percent);
        }
    }


    Dictionary<string, AsyncOperationHandle> createHandleDic = new Dictionary<string, AsyncOperationHandle>();

    async Task CreatePrefab(string prefabName)
    {
        string path = $"Assets/Prefabs/{prefabName}.prefab";
        AsyncOperationHandle handle;
        if (!createHandleDic.TryGetValue(prefabName, out handle)
            || !handle.IsValid())
        {
            handle = Addressables.InstantiateAsync(path);
            createHandleDic.Add(prefabName, handle);
            handle.Completed += InstantiateObject;
        }
        else
        {
            handle = createHandleDic[prefabName];
            if (handle.IsDone)
            {
                InstantiateObject(handle);
            }
            else
            {
                handle.Completed += InstantiateObject;
            }
        }
    }

    async Task ReleaseHandle(string prefabName)
    {
        if (createHandleDic.TryGetValue(prefabName ,out AsyncOperationHandle handle))
        {
            Addressables.Release(handle);
            createHandleDic.Remove(prefabName);
        }
    }

    void UnloadUnusedAssets()
    {
        Resources.UnloadUnusedAssets();
    }

    void InstantiateObject(AsyncOperationHandle handle)
    {
        var obj = handle.Result as GameObject;
        // var go = Instantiate(obj).AddComponent<Cube>();
        obj.AddComponent<Cube>();
        obj.transform.SetParent(Camera.main.transform);
        obj.transform.localPosition = new Vector3(count, 0, 20);
        count++;
    }

    void SwitchCdnUrl(string CDNPath, string version)
    {
        var catalogPath = $"{CDNPath}/catalog_{version}.json";
        //Load a catalog and automatically release the operation handle.
        curUrl = CDNPath;
        Addressables.InternalIdTransformFunc = InternalIdTransformFunc;
        AsyncOperationHandle<UnityEngine.AddressableAssets.ResourceLocators.IResourceLocator> handle
            = Addressables.LoadContentCatalogAsync(catalogPath, true);
        handle.Completed += operationHandle =>
        {
            Debug.Log(operationHandle.Result);
        };
    }

    string InternalIdTransformFunc(IResourceLocation location)
    {
        return location.InternalId.Replace(cdnUrl1 + "/", curUrl + "/");
    }
    
    IEnumerator CopyBuildInManifest()
    {
        
        yield return null;
    }

    private int count = -5;
    
    void CreatePackageBtn(string pkgName)
    {
        GUILayout.BeginHorizontal();

        if (GUILayout.Button($"创建红色"))
        {
            _ = CreatePrefab("RedCube");
        }

        if (GUILayout.Button($"创建蓝色"))
        {

            _ = CreatePrefab("BlueCube");
        }
        
        if (GUILayout.Button($"卸载蓝色"))
        {
            ReleaseHandle("BlueCube");
        }

        if (GUILayout.Button($"卸载红色"))
        {
            ReleaseHandle("RedCube");
        }
        if (GUILayout.Button($"释放无用资源"))
        {
            UnloadUnusedAssets();
        }
        if (GUILayout.Button($"检查更新"))
        {
            _ = CheckUpdate();
        }

        if (GUILayout.Button($"更新catalogs"))
        {
            _ = UpdateCatalogs(catalogs);
        }
        
        if (GUILayout.Button($"下载资源"))
        {
            _ = Download(updateList);
        }
        GUILayout.EndHorizontal();
    }
    
    string version = "1.0";
    int cdnIdx = 0;
    private void OnGUI()
    {
        CreatePackageBtn(packageName);
        // CreatePackageBtn(packageName2);
        GUILayout.BeginHorizontal();
        version = GUILayout.TextField(version, GUILayout.Width(100));
        cdnIdx = GUILayout.Toolbar(cdnIdx, new string[] { cdnUrl1, cdnUrl2 });
        if (GUILayout.Button("切换地址"))
        {
            SwitchCdnUrl(cdnIdx == 0 ? cdnUrl1 : cdnUrl2, version);
        }
        if (GUILayout.Button("删除所有方块"))
        {
            // 获取当前游戏对象的所有子节点数量
            int childCount = Camera.main.transform.childCount;

            // 遍历所有子节点并销毁它们
            for (int i = childCount - 1; i >= 0; i--)
            {
                // 获取当前子节点
                Transform child = Camera.main.transform.GetChild(i);
                // 销毁当前子节点
                Destroy(child.gameObject);
            }

            count = -5;
        }

        // if (GUI.Button(new Rect(680, 20, 100, 20), "清除log"))
        if (GUILayout.Button("清除log"))
        {
            logStr = "";
        }

        GUILayout.EndHorizontal();
        GUILayout.BeginScrollView(new Vector2(0, 0));
        GUILayout.Label(logStr);
        GUILayout.EndScrollView();
    }
}

